﻿using System;
using Notoric.Commanding.CommandBase;

namespace Notoric.ViewModel.Elements
{
    /// <summary>
    /// Adapts a <see cref="Model.Elements.PartDescriptorElement"/> to a Windows Presentation Foundation view.
    /// </summary>
    public class PartDescriptor : ViewModelElement
    {
        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="PartDescriptor"/> class.
        /// </summary>
        /// <param name="adaptedElement">
        /// <para>
        /// Type: <see cref="Model.Elements.PartDescriptorElement"/>
        /// </para>
        /// <para>
        /// The adapted element.
        /// </para>
        /// </param>
        /// <param name="owner">
        /// <para>
        /// Type: <see cref="Composition"/>
        /// </para>
        /// <para>
        /// The composition that owns this part descriptor.
        /// </para>
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// The <paramref name="adaptedElement"/> is <see langword="null"/>.
        /// </exception>
        /// <exception cref="NullReferenceException">
        /// The <paramref name="owner"/> is <see langword="null"/>.
        /// </exception>
        public PartDescriptor(Model.Elements.PartDescriptorElement adaptedElement, Composition owner)
            : base(adaptedElement, owner, owner.UndoStack, owner.RedoStack)
        {
        }

        #endregion

        #region ViewModelElement Members

        /// <inheritdoc/>
        public override string ElementNameKey
        {
            get { return elementNameKey; }
        }

        #endregion

        #region Public Methods

        /// <summary>
        /// Creates an undoable command for setting the abbeviation of the part's name.
        /// </summary>
        /// <param name="abbreviation">
        /// <para>
        /// Type: <see cref="String"/>
        /// </para>
        /// <para>
        /// The new abbreviation.
        /// </para>
        /// </param>
        /// <returns>
        /// <para>
        /// Type: <see cref="UndoableCommandBase"/>
        /// </para>
        /// <para>
        /// The created command ready for use.
        /// </para>
        /// </returns>
        public UndoableCommandBase CreateSetAbbreviationCommand(string abbreviation)
        {
            return new SetterCommand<string>(this, "Abbreviation", abbreviation, UndoStack, RedoStack);
        }

        /// <summary>
        /// Creates an undoable command for setting the name of the part.
        /// </summary>
        /// <param name="name">
        /// <para>
        /// Type: <see cref="String"/>
        /// </para>
        /// <para>
        /// The new name.
        /// </para>
        /// </param>
        /// <returns>
        /// <para>
        /// Type: <see cref="UndoableCommandBase"/>
        /// </para>
        /// <para>
        /// The created command ready for use.
        /// </para>
        /// </returns>
        public UndoableCommandBase CreateSetNameCommand(string name)
        {
            return new SetterCommand<string>(this, "Name", name, UndoStack, RedoStack);
        }

        #endregion

        #region Public Properties

        /// <summary>
        /// Gets or sets the abbreviation of the part's name.
        /// </summary>
        /// <value>
        /// <para>
        /// Type: <see cref="string"/>
        /// </para>
        /// <para>
        /// The abbreviation of the part's name.
        /// </para>
        /// </value>
        public string Abbreviation
        {
            get { return GetPropertyValue<string>("Abbreviation"); }
            set
            {
                if (UnsavedChanges.ContainsKey("Abbreviation"))
                {
                    var cmd = (SetterCommand<string>)UnsavedChanges["Abbreviation"];
                    cmd.Value = value;
                }
                else
                    UnsavedChanges["Abbreviation"] = CreateSetNameCommand(value);

                RaisePropertyChanged("Abbreviation");
            }
        }

        /// <summary>
        /// Gets or sets the name of the part.
        /// </summary>
        /// <value>
        /// <para>
        /// Type: <see cref="string"/>
        /// </para>
        /// <para>
        /// The name of the part.
        /// </para>
        /// </value>
        public string Name
        {
            get { return GetPropertyValue<string>("Name"); }
            set
            {
                if (UnsavedChanges.ContainsKey("Name"))
                {
                    var cmd = (SetterCommand<string>)UnsavedChanges["Name"];
                    cmd.Value = value;
                }
                else
                    UnsavedChanges["Name"] = CreateSetNameCommand(value);

                RaisePropertyChanged("Name");
            }
        }

        #endregion

        #region Private Fields

        /// <summary>
        /// Holds the key of a user-friendly name of this element.
        /// </summary>
        private const string elementNameKey = "ViewModel.ElementNames.PartDescriptor";

        #endregion
    }
}
